home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / perl / perlvisi.1 / perlvisi / perlvision / perlvision.pl < prev    next >
Encoding:
Text File  |  1995-03-22  |  35.9 KB  |  1,584 lines

  1. require 5.000;
  2.  
  3. # PerlVision - A class library to do ANSI graphics and textmode GUI
  4. # By Ashish Gulhati (hash@well.sf.ca.us)
  5. # V.0.1.0
  6. #
  7. # (C) Ashish Gulhati, 1995. All Rights Reserved.
  8. #
  9. # Free electronic distribution permitted. You are free to use
  10. # PerlVision in your own code so long as this copyright message stays
  11. # intact. PerlVision or derived code may not be used in any commercial
  12. # product without my prior written or PGP-signed consent. Please e-mail 
  13. # me if you make significant changes, or just want to let me know what 
  14. # you're using PerlVision for.
  15.  
  16. require "pvbasic.pl";
  17.  
  18. package PV_Static;        # Trivial static text class for dialog boxes
  19.  
  20. sub new {
  21.     my $type=shift;
  22.     my @params=@_;
  23.     my $self=\@params;
  24.     bless $self;
  25. }
  26.  
  27. sub place {
  28.     my $self=shift;
  29.     my ($message,$x1,$y1,$x2,$y2)=@$self[0..4];
  30.     my @message=split("\n",$message);
  31.     my $width=$x2-$x1;
  32.     my $depth=$y2-$y1;
  33.     my $i=$y1;
  34.     &pv::fgcolor(0);
  35.     &pv::bgcolor(6);
  36.     foreach (@message[0..$depth]) {
  37.     &pv::set_cur_pos($x1,$i);
  38.     &pv::pvprint (substr ($_,0,$width));
  39.     $i++;
  40.     }
  41. }
  42.  
  43. sub display {
  44.     my $self=shift;
  45.     $self->place;
  46.     &pv::refresh();
  47. }
  48.  
  49. package PV_Checkbox;
  50.  
  51. sub new {            # Creates your basic check box
  52.     my $type = shift;        # $foo = new PV_Checkbox (Label,x,y,stat);
  53.     my @params = @_;        
  54.     my $self = \@params;
  55.     bless $self;
  56.     return $self;
  57. }
  58.  
  59. sub place {            
  60.     my $self = shift;        
  61.     pv::set_cur_pos($$self[1],$$self[2]); 
  62.     pv::bgcolor(6); pv::fgcolor(15); &pv::pvprint("["); pv::fgcolor(0);
  63.     ($$self[3]) && &pv::pvprint($pv::TICK);
  64.     ($$self[3]) || &pv::pvprint(" ");
  65.     pv::fgcolor(15); &pv::pvprint("]"); pv::fgcolor(0); 
  66.     &pv::pvprint(" $$self[0]");
  67. }
  68.  
  69. sub display {
  70.     my $self=shift;
  71.     $self->place;
  72.     &pv::refresh();
  73. }
  74.  
  75. sub refresh {            # Refreshes display of your check box
  76.     my $self = shift;
  77.     pv::set_cur_pos($$self[1]+1,$$self[2]); 
  78.     pv::bgcolor(6); pv::fgcolor(0);
  79.     ($$self[3]) && &pv::pvprint($pv::TICK);
  80.     ($$self[3]) || &pv::pvprint(" ");
  81.     pv::set_cur_pos($$self[1]+1,$$self[2]); 
  82.     &pv::refresh();
  83. }
  84.  
  85. sub activate {            # Makes checkbox active
  86.     my $self = shift;        # $foo->activate;
  87.     my @key;
  88.     $self->refresh;
  89.     &pv::refresh_cursor();
  90.     while (@key = pv::getkey()) {
  91.  
  92.     if ($key[1]==7) {    # UpArrow
  93.         return 1;
  94.     }
  95.     elsif ($key[1]==8) {    # DnArrow
  96.         return 2;
  97.     }
  98.     elsif ($key[1]==9) {    # RightArrow
  99.         return 3;
  100.     }
  101.     elsif ($key[1]==10) {    # LeftArrow
  102.         return 4;
  103.     }
  104.     elsif ($key[1]==18) {    # Help
  105.         return 5;
  106.     }
  107.     elsif ($key[1]==19) {    # Menu
  108.         return 6;
  109.     }
  110.     elsif (($key[0] eq "\t") && ($key[1]==200)) { 
  111.         return 7;
  112.     }
  113.  
  114.     elsif (($key[0] eq ' ') && ($key[1]==200)) {
  115.         $self->select;
  116.     }
  117.     $self->refresh;
  118.     &pv::refresh_cursor();
  119.     }
  120. }
  121.  
  122. sub select {            # Toggles checkbox status
  123.     my $self = shift;
  124.     $$self[3] = ($$self[3] ? 0 : 1);
  125. }
  126.  
  127. sub stat {            # Returns status of checkbox
  128.     my $self = shift;        # $bar = $foo->status;
  129.     return $$self[3];
  130. }
  131.  
  132. package PV_Radio;
  133.  
  134. @ISA = (PV_Checkbox);
  135.  
  136. sub new {            # Creates your basic radio button
  137.     my $type = shift;        # $foo = new PV_Radio (Label,x,y,stat);
  138.     my @params = (@_,0);
  139.     my $self = \@params;
  140.     bless $self;
  141.     return $self;
  142. }
  143.  
  144. sub place {            # Displays a radio button
  145.     my $self = shift;        # $foo->display;
  146.     pv::set_cur_pos($$self[1],$$self[2]); 
  147.     pv::bgcolor(6); pv::fgcolor(15); &pv::pvprint("("); pv::fgcolor(0);
  148.     ($$self[3]) && &pv::pvprint($pv::MARK);
  149.     ($$self[3]) || &pv::pvprint(" ");
  150.     pv::fgcolor(15); &pv::pvprint(")"); pv::fgcolor(0); 
  151.     &pv::pvprint(" $$self[0]");
  152. }
  153.  
  154. sub display {
  155.     my $self=shift;
  156.     $self->place;
  157.     &pv::refresh();
  158. }
  159.  
  160. sub refresh {            # Refreshes display of your check box
  161.     my $self = shift;
  162.     pv::set_cur_pos($$self[1]+1,$$self[2]); 
  163.     pv::bgcolor(6); pv::fgcolor(0);
  164.     ($$self[3]) && &pv::pvprint($pv::MARK);
  165.     ($$self[3]) || &pv::pvprint(" ");
  166.     pv::set_cur_pos($$self[1]+1,$$self[2]); 
  167.     &pv::refresh();
  168. }
  169.  
  170. sub group {            # Puts the button in a group
  171.     my $self = shift;        # Should not be called from user programs
  172.     $$self[5] = shift;
  173. }
  174.  
  175. sub select {            # Turn radio button on
  176.     my $self = shift;
  177.     unless ($$self[3]) {
  178.     $$self[5]->blank if $$self[5];
  179.     $$self[3] = 1;
  180.     $$self[5]->refresh;
  181.     }
  182. }
  183.  
  184. sub unselect {            # Turn radio button off
  185.     my $self = shift;
  186.     $$self[3] = 0;
  187. }
  188.  
  189. package PV_RadioG;
  190.             
  191. sub new {            # Creates your basic radio button group
  192.     my $type = shift;        # $foo = new PV_RadioG (rb1, rb2, rb3...)
  193.     my @params = @_;        # where rbn is of class PV_Radio
  194.     my $self = \@params;
  195.     my $i;
  196.     bless $self;
  197.     foreach $i (@$self) {
  198.     ($i->group($self));
  199.     }
  200.     return $self;
  201. }
  202.  
  203. sub place {
  204.     my $self = shift;
  205.     my $i;
  206.     foreach $i (@$self) {
  207.     $i->display;
  208.     }
  209. }
  210.  
  211. sub display {
  212.     my $self=shift;
  213.     $self->place;
  214.     &pv::refresh();
  215. }
  216.  
  217. sub refresh {
  218.     my $self = shift;
  219.     my $i;
  220.     foreach $i (@$self) {
  221.     $i->refresh;
  222.     }
  223.     &pv::refresh();
  224. }
  225.  
  226. sub blank {            # Unchecks all buttons in the group
  227.     my $self = shift;
  228.     my $i;
  229.     foreach $i (@$self) {
  230.     $i->unselect;
  231.     }
  232. }
  233.     
  234. sub stat {            # Returns label of selected radio button
  235.     my $self = shift;
  236.     my $i;
  237.     foreach $i (@$self) {
  238.     ($i->stat) && (return $$i[0]);
  239.     }
  240.     return undef;
  241. }
  242.  
  243. package PV_Pushbutton;
  244.  
  245. sub new {            # Creates a basic pushbutton
  246.     my $type = shift;        # PV_Pushbutton ("Label",x1,y1);
  247.     my @params= @_;
  248.     my $self = \@params;
  249.     bless $self;
  250. }
  251.  
  252. sub place {
  253.     my $self=shift;
  254.     pv::box(@$self[1..2],$$self[1]+length($$self[0])+3,$$self[2]+2,1,7);
  255.     pv::fgcolor(15); pv::set_cur_pos($$self[1]+2,$$self[2]+1);
  256.     &pv::pvprint($$self[0]);
  257. }    
  258.  
  259. sub display {
  260.     my $self=shift;
  261.     $self->place;
  262.     &pv::refresh();
  263. }
  264.  
  265. sub press {
  266.     my $self=shift;
  267.     pv::box(@$self[1..2],$$self[1]+length($$self[0])+3,$$self[2]+2,0,7);
  268.     pv::fgcolor(0); pv::set_cur_pos($$self[1]+2,$$self[2]+1);
  269.     pv::pvprint($$self[0]);
  270.     pv::refresh();
  271. }
  272.  
  273. sub active {
  274.     my $self=shift;
  275.     pv::bgcolor(7);
  276.     pv::fgcolor(0); pv::set_cur_pos($$self[1]+2,$$self[2]+1);
  277.     &pv::pvprint($$self[0]);
  278.     pv::refresh();
  279. }
  280.  
  281. sub activate {
  282.     my $self=shift;
  283.     $self->active;
  284.     while (@key = pv::getkey()) {
  285.  
  286.     if ($key[1]==7) {    # UpArrow
  287.         $self->display;
  288.         return 1;
  289.     }
  290.     elsif ($key[1]==8) {    # DnArrow
  291.         $self->display;
  292.         return 2;
  293.     }
  294.     elsif ($key[1]==9) {    # RightArrow
  295.         $self->display;
  296.         return 3;
  297.     }
  298.     elsif ($key[1]==10) {    # LeftArrow
  299.         $self->display;
  300.         return 4;
  301.     }
  302.     elsif ($key[1]==18) {    # Help
  303.         $self->display;
  304.         return 5;
  305.     }
  306.     elsif ($key[1]==19) {    # Menu
  307.         $self->display;
  308.         return 6;
  309.     }
  310.     elsif (($key[0] eq "\t") && ($key[1]==200)) { 
  311.         $self->display;
  312.         return 7;
  313.     }
  314.  
  315.     elsif (($key[0] =~ /[ \n]/) && ($key[1]==200)) {
  316.         $self->press;
  317.         return 8;
  318.     }
  319.     }
  320. }
  321.  
  322. package PV_Cutebutton;
  323.  
  324. @ISA = (PV_Pushbutton);
  325.  
  326. sub new {            # A smaller, cuter pushbutton
  327.     my $type = shift;        # PV_Pushbutton ("Label",x1,y1);
  328.     my @params= @_;
  329.     my $self = \@params;
  330.     bless $self;
  331. }
  332.  
  333. sub place {
  334.     my $self=shift;
  335.     pv::fgcolor(15); pv::set_cur_pos($$self[1],$$self[2]);
  336.     &pv::pvprint("  ".$$self[0]." "); pv::fgcolor(0); pv::pvprint($pv::VT);
  337.     pv::fgcolor(15); pv::set_cur_pos($$self[1],$$self[2]+1);
  338.     &pv::pvprint($pv::BL);pv::fgcolor(0);
  339.     &pv::pvprint(($pv::HZ x (length($$self[0])+2)).$pv::BR);
  340. }    
  341.  
  342. sub display {
  343.     my $self=shift;
  344.     $self->place;
  345.     &pv::refresh();
  346. }
  347.  
  348. sub press {
  349.     my $self=shift;
  350.     pv::fgcolor(0); pv::set_cur_pos($$self[1],$$self[2]);
  351.     &pv::pvprint(($pv::TL.($pv::HZ x (length($$self[0])+2))));
  352.     pv::fgcolor(15); pv::pvprint($pv::TR);
  353.     pv::set_cur_pos($$self[1],$$self[2]+1); pv::fgcolor(0);
  354.     &pv::pvprint($pv::VT);
  355.     pv::fgcolor(4); pv::pvprint (" ".$$self[0]."  ");
  356.     pv::refresh();
  357. }
  358.  
  359. sub active {
  360.     my $self=shift;
  361.     pv::fgcolor(4); pv::set_cur_pos($$self[1]+2,$$self[2]);
  362.     &pv::pvprint($$self[0]);
  363.     pv::refresh();
  364. }
  365.  
  366. package PV_Plainbutton;
  367.  
  368. @ISA = (PV_Pushbutton);
  369.  
  370. sub new {            # A minimal pushbutton
  371.     my $type = shift;        # PV_Pushbutton ("Label",x1,y1);
  372.     my @params= @_;
  373.     my $self = \@params;
  374.     bless $self;
  375. }
  376.  
  377. sub place {
  378.     my $self=shift;
  379.     pv::fgcolor(15); pv::bgcolor(6); pv::set_cur_pos($$self[1],$$self[2]);
  380.     &pv::pvprint($$self[0])
  381. }    
  382.  
  383. sub display {
  384.     my $self=shift;
  385.     $self->place;
  386.     &pv::refresh();
  387. }
  388.  
  389. sub press {
  390. }
  391.  
  392. sub active {
  393.     my $self=shift;
  394.     pv::bgcolor(4); pv::fgcolor(15); pv::set_cur_pos($$self[1],$$self[2]);
  395.     &pv::pvprint($$self[0]);
  396.     pv::refresh();
  397. }
  398.  
  399. package PV_SListbox;
  400.  
  401. sub new {            # Creates a superclass list box
  402.     my $type = shift;        # PV_SListbox (Head,top,x1,y1,x2,y2,list)
  403.     my $head = shift;
  404.     my @params = ($head,0,@_);    # where list is (l1,s1,l2,s2,...)
  405.     my $self = \@params;    # Do not use from outside
  406.     bless $self;
  407. }
  408.  
  409. sub place {
  410.     my $self = shift;
  411.     my ($top,$x1,$y1,$x2,$y2) = @$self[1..5];
  412.     $self->draw_border;
  413.     my $i = shift;
  414.     $i *= 2;
  415.     $x1++; $y1++;
  416.     while (($y1 < $y2) && ($i+6 < $#$self)) {
  417.     ($$self[7+$i]) && ($self->selected($y1,$i));
  418.     ($$self[7+$i]) || ($self->unselected($y1,$i));
  419.     $y1++;
  420.     $i += 2;
  421.     }
  422. }
  423.  
  424. sub display {
  425.     my $self=shift;
  426.     $self->place;
  427.     &pv::refresh();
  428. }
  429.  
  430. sub refresh {
  431.     my $self = shift;
  432.     my ($top,$x1,$y1,$x2,$y2) = @$self[1..5];
  433.     my $i = shift;
  434.     unless ($i==$top) {
  435.     $$self[1]=$i;
  436.     $i *= 2;
  437.     $x1++; $y1++;
  438.     while (($y1 < $y2) && ($i+6 < $#$self)) {
  439.         ($$self[7+$i]) && ($self->selected($y1,$i));
  440.         ($$self[7+$i]) || ($self->unselected($y1,$i));
  441.         $y1++;
  442.         $i += 2;
  443.     }
  444.     }
  445.     &pv::refresh();
  446. }
  447.  
  448. sub unhighlight {
  449.     my $self = shift;
  450.     my ($ypos,$i) = @_;
  451.     ($$self[7+$i]) && ($self->selected($ypos,$i));
  452.     ($$self[7+$i]) || ($self->unselected($ypos,$i));
  453.     &pv::refresh();
  454. }
  455.  
  456. sub highlight {
  457.     my $self = shift;
  458.     my $ypos = shift;
  459.     my $i = shift;
  460.     my ($x1,$x2) = @$self[2,4];
  461.     $x1++;
  462.     pv::bgcolor(4); pv::fgcolor(15);
  463.     pv::set_cur_pos($x1+1,$ypos);
  464.     &pv::pvprint (substr ($$self[6+$i],0,$x2-$x1-2).
  465.          " " x 
  466.          ($x2-$x1-2-length(substr($$self[6+$i],0,$x2-$x1-2))));
  467.     &pv::refresh();
  468. }
  469.  
  470. sub selected {
  471.     my $self = shift;
  472.     my $ypos = shift;
  473.     my $i = shift;
  474.     $self->unselected($ypos,$i);
  475. }
  476.  
  477. sub reset {
  478.     my $self = shift;
  479.     my $i;
  480.     for ($i=7; $i <= $#$self; $i +=2) {
  481.     $$self[$i] = 0;
  482.     }
  483.     $self->refresh(0);
  484. }
  485.  
  486. sub stat {
  487.     my $self = shift;
  488.     my $i;
  489.     my @returnlist = ();
  490.     for ($i=7; $i <= $#$self; $i +=2) {
  491.     ($$self[$i]) && (@returnlist = (@returnlist,$$self[$i-1]));
  492.     }
  493.     $self->reset;
  494.     return @returnlist;
  495. }
  496.  
  497. sub done {
  498.     my $self = shift;
  499.     my $i = shift;
  500.     $$self[$i*2+7]=1;
  501.     $self->refresh(0);
  502. }
  503.  
  504. sub deactivate {
  505.     my $self = shift;
  506.     $self->reset();
  507. }
  508.  
  509. sub unselected {
  510.     my $self = shift;
  511.     my $ypos = shift;
  512.     my $i = shift;
  513.     my ($x1,$x2) = @$self[2,4];
  514.     $x1++;
  515.     pv::bgcolor(6); pv::fgcolor(0);
  516.     pv::set_cur_pos($x1+1,$ypos);
  517.     &pv::pvprint (substr ($$self[6+$i],0,$x2-$x1-2).
  518.          " " x 
  519.          ($x2-$x1-2-length(substr($$self[6+$i],0,$x2-$x1-2))));
  520. }
  521.  
  522. sub activate {
  523.     my $self = shift;
  524.     my ($x1,$y1,$x2,$y2) = @$self[2..5];
  525.     my $i = 0;
  526.     my @key;
  527.     $x1++; $y1++;
  528.     my $ypos=$y1;
  529.     $self->refresh($i);
  530.     $self->highlight($y1,$i*2);
  531.     while (@key = pv::getkey()) {
  532.  
  533.     if ($key[1]==18) {    # Help
  534.         $self->unhighlight($ypos,$i*2);
  535.         $self->deactivate();
  536.         return 5;
  537.     }
  538.     elsif ($key[1]==19) {    # Menu
  539.         $self->unhighlight($ypos,$i*2);
  540.         $self->deactivate();
  541.         return 6;
  542.     }
  543.     elsif ($key[1]==9) {    # RightArrow
  544.         $self->unhighlight($ypos,$i*2);
  545.         $self->deactivate();
  546.         return 3;
  547.     }
  548.     elsif ($key[1]==10) {    # LeftArrow
  549.         $self->unhighlight($ypos,$i*2);
  550.         $self->deactivate();
  551.         return 4;
  552.     }
  553.     elsif (($key[0] eq "\t") && ($key[1]==200)) { 
  554.         $self->unhighlight($ypos,$i*2);
  555.         $self->deactivate();
  556.         return 7;
  557.     }
  558.         elsif (($key[0] eq "\n") && ($key[1] == 200)) {
  559.         $self->unhighlight($ypos,$i*2);
  560.         $self->done($i);
  561.         return 8;        
  562.     }
  563.     elsif (($key[0] eq " ") && ($key[1] == 200)) {
  564.         $self->select($i);
  565.         $self->highlight($ypos,$i*2);
  566.     }
  567.     elsif (($key[1] == 7) && ($i != 0)) { # Up
  568.         ($ypos == $y1) || do {$self->unhighlight($ypos,$i*2); $ypos--};
  569.         $i--;
  570.         $self->refresh($i-$ypos+$y1);
  571.         $self->highlight($ypos,$i*2);
  572.     }
  573.     elsif (($key[1] == 8) && (($i*2+7) < $#$self)) { # Down
  574.         ($ypos == $y2-1) || do {$self->unhighlight($ypos,$i*2); $ypos++};
  575.         $i++;
  576.         $self->refresh($i-$ypos+$y1);
  577.         $self->highlight($ypos,$i*2);
  578.     }
  579.     }
  580. }
  581.  
  582. sub draw_border {
  583.     my $self = shift;
  584.     pv::box(@$self[2..5],0,6);
  585.     pv::fgcolor(15); pv::set_cur_pos($$self[2],$$self[3]);
  586.     &pv::pvprint($$self[0]);
  587. }
  588.  
  589. sub select {
  590. }
  591.  
  592. package PV_Listbox;
  593.  
  594. @ISA = (PV_SListbox);
  595.  
  596. sub new {            # Basic single selection listbox
  597.     my $type = shift;        # PV_Listbox (Head,x1,y1,x2,y2,list)
  598.     my @params = @_;        # where list is (l1,s1,l2,s2,...)
  599.     my $self = new PV_SListbox(@params);
  600.     bless $self;
  601. }
  602.  
  603. package PV_Mlistbox;
  604.  
  605. @ISA = (PV_SListbox);
  606.  
  607. sub new {            # A multiple selection listbox
  608.     my $type = shift;        # PV_Mlistbox (Head,x1,y1,x2,y2,list)
  609.     my @params = @_;        # where list is (l1,s1,l2,s2,...)
  610.     my $self = new PV_SListbox(@params);
  611.     bless $self;
  612. }
  613.  
  614. sub select {
  615.     my $self = shift;
  616.     my $i = shift;
  617.     if ($$self[7+$i*2]) {
  618.     $$self[7+$i*2] = 0;
  619.     }
  620.     else {
  621.     $$self[7+$i*2] = 1;
  622.     }
  623. }
  624.  
  625. sub selected {
  626.     my $self = shift;
  627.     my $ypos = shift;
  628.     my $i = shift;
  629.     my ($x1,$x2) = @$self[2,4];
  630.     $x1++;
  631.     pv::bgcolor(6); pv::fgcolor(10);
  632.     pv::set_cur_pos($x1+1,$ypos);
  633.     &pv::pvprint (substr ($$self[6+$i],0,$x2-$x1-2).
  634.          " " x 
  635.          ($x2-$x1-2-length(substr($$self[6+$i],0,$x2-$x1-2))));
  636. }
  637.  
  638. sub highlight {
  639.     my $self = shift;
  640.     my $ypos = shift;
  641.     my $i = shift;
  642.     my ($x1,$x2) = @$self[2,4];
  643.     $x1++;
  644.     pv::bgcolor(4); pv::fgcolor(15-5*$$self[7+$i]);
  645.     pv::set_cur_pos($x1+1,$ypos);
  646.     &pv::pvprint (substr ($$self[6+$i],0,$x2-$x1-2).
  647.          " " x 
  648.          ($x2-$x1-2-length(substr($$self[6+$i],0,$x2-$x1-2))));
  649.     &pv::refresh();
  650. }
  651.  
  652. sub deactivate {
  653.     my $self = shift;
  654.     $self->refresh();
  655. }
  656.  
  657. sub done {
  658.     my $self = shift;
  659.     $self->refresh();
  660. }
  661.  
  662. package PV_Pulldown;
  663.  
  664. @ISA = (PV_SListbox);
  665.  
  666. sub new {            # A pulldown menu box. Used by PV_Menubar
  667.     my $type = shift;        # Don't use from outside
  668.     my @params = (@_);
  669.     my $self = new PV_SListbox(@params);
  670.     bless $self;
  671. }
  672.  
  673. sub draw_border {
  674.     my $self = shift;
  675.     pv::set_cur_pos(@$self[2..3]);
  676.     &pv::bgcolor(7);
  677.     pv::fgcolor(15);
  678.     &pv::pvprint (($$self[2] == 2) ? $pv::VT : $pv::TR);
  679.     pv::fgcolor(0);
  680.     &pv::pvprint(" " x ($$self[4]-$$self[2]-1).(($$self[4] == 79) ? $pv::VT : $pv::TL));
  681.     my $lines=$$self[4]-$$self[2];
  682.     my $j;
  683.     for ($j=$$self[3]+1; $j<$$self[5]; $j++) {
  684.     &pv::set_cur_pos($$self[2],$j);
  685.     &pv::fgcolor (15); &pv::pvprint ($pv::VT);
  686.     &pv::pvprint (" " x ($lines-1));
  687.     &pv::fgcolor (0); &pv::pvprint ($pv::VT); 
  688.     }
  689.     &pv::set_cur_pos($$self[2],$$self[5]); 
  690.     &pv::fgcolor (15); &pv::pvprint ($pv::BL); 
  691.     &pv::fgcolor (0); &pv::pvprint ($pv::HZ x ($lines-1));
  692.     &pv::pvprint ($pv::BR);
  693. }
  694.  
  695. sub unselected {
  696.     my $self = shift;
  697.     my $ypos = shift;
  698.     my $i = shift;
  699.     my ($x1,$x2) = @$self[2,4];
  700.     $x1++;
  701.     pv::bgcolor(7); pv::fgcolor(4);
  702.     pv::set_cur_pos($x1+1,$ypos);
  703.     &pv::pvprint (substr ($$self[6+$i],0,$x2-$x1-2).
  704.          " " x 
  705.          ($x2-$x1-2-length(substr($$self[6+$i],0,$x2-$x1-2))));
  706. }
  707.  
  708. sub activate {
  709.     my $self=shift;
  710.     my $savestate=&pv::pv_tellregion(@$self[2..3],$$self[4]+1,$$self[5]);
  711.     $self->display();
  712.     my $ret=$self->PV_SListbox::activate();
  713.     &pv::pv_putregion(@$self[2..3],$$self[4]+1,$$self[5],$savestate);
  714.     &pv::refresh;
  715.     return ($ret,$self->stat());
  716. }
  717.  
  718. package PV_Menubar;        
  719.  
  720. sub new {            # A menu bar with pulldowns
  721.     my $type=shift;        # new PV_Menubar(Head,width,depth,l,0,l,0,l,0,l,0,l);
  722.     my @params=@_;
  723.     my $pulldown = new PV_Pulldown ($params[0],2,3,$params[1]+2,$params[2]+3,@params[3..$#params]);
  724.     my $self=[$pulldown];
  725.     bless $self;
  726. }
  727.  
  728. sub add {            # Add a pulldown to the menubar
  729.     my $self=shift;        # $foo->add(Head,width,depth,l,0,l,0,l,0,l,0,l);
  730.     my @params=@_;
  731.     my $pulldown = new PV_Pulldown ($params[0],2+(10*($#$self+1)),3,
  732.                     $params[1]+2+(10*($#$self+1)),$params[2]+3,
  733.                     @params[3..$#params]);
  734.     $$self[$#$self+1]=$pulldown;
  735. }
  736.  
  737. sub highlight {
  738.     my $self=shift;
  739.     my $i=shift;
  740.     &pv::set_cur_pos (4+10*$i,2);
  741.     &pv::bgcolor(4); &pv::fgcolor(14);
  742.     &pv::pvprint($$self[$i][0]);
  743.     &pv::refresh();
  744. }
  745.  
  746. sub unhighlight {
  747.     my $self=shift;
  748.     my $i=shift;
  749.     &pv::set_cur_pos (4+10*$i,2);
  750.     &pv::bgcolor(7); &pv::fgcolor(0);
  751.     &pv::pvprint($$self[$i][0]);
  752.     &pv::refresh();
  753. }
  754.  
  755. sub activate {
  756.     my $self=shift;
  757.     my $i=0;
  758.     my @key;
  759.     my @ret;
  760.     $self->highlight($i);
  761.     while (@key = pv::getkey()) {
  762.  
  763.     if ($key[1]==18) {    # Help
  764.         $self->unhighlight($i);
  765.         return 5;
  766.     }
  767.     elsif ($key[1]==9) {    # RightArrow
  768.         $$self[$i]->reset();
  769.         $self->unhighlight($i);
  770.         $i = ($i==$#$self ? 0 : $i+1);
  771.         $self->highlight($i);
  772.     }
  773.     elsif ($key[1]==10) {    # LeftArrow
  774.         $$self[$i]->reset();
  775.         $self->unhighlight($i);
  776.         $i = ($i==0 ? $#$self : $i-1);
  777.         $self->highlight($i);
  778.     }
  779.     elsif (($key[0] eq "\t") && ($key[1]==200)) { 
  780.         $self->unhighlight($i);
  781.         return 7;
  782.     }
  783.         elsif ((($key[0] eq "\n") && ($key[1] == 200)) || ($key[1] == 8))  {
  784.         while (@ret = ($$self[$i]->activate())) {
  785.         if ($ret[0]==3) {
  786.             $$self[$i]->reset();
  787.             $self->unhighlight($i);
  788.             $i = ($i==$#$self ? 0 : $i+1);
  789.             $self->highlight($i);
  790.         }
  791.         elsif ($ret[0]==4) {
  792.             $$self[$i]->reset();
  793.             $self->unhighlight($i);
  794.             $i = ($i==0 ? $#$self : $i-1);
  795.             $self->highlight($i);
  796.         }
  797.         else {
  798.             last;
  799.         }
  800.         }
  801.         if ($ret[0] == 5) {
  802.         $self->unhighlight($i);
  803.         return 5;
  804.         }
  805.         elsif ($ret[0] == 8) {
  806.         $self->unhighlight($i);
  807.         return (8,$$self[$i][0].":".$ret[1]);
  808.         }
  809.     }
  810.     }
  811. }
  812.  
  813. sub place {
  814.     my $self=shift;
  815.     my ($i);
  816.     &pv::box (2,1,79,3,1,7);
  817.     for ($i=0; $i <=$#$self; $i++) {
  818.     &pv::set_cur_pos (4+10*$i,2);
  819.     &pv::pvprint($$self[$i][0]);
  820.     }
  821. }
  822.  
  823. sub display {
  824.     my $self=shift;
  825.     $self->place;
  826.     &pv::refresh();
  827. }
  828.  
  829. package PV_Entryfield;
  830.  
  831. sub new {            # Creates your basic text entry field
  832.     my $type = shift;        # new PV_Entryfield(x,y,len,start,label,value);
  833.     my @params = @_;
  834.     my $self = \@params;
  835.     bless $self;
  836. }
  837.  
  838. sub place {
  839.     my $self = shift;
  840.     my $start = shift;
  841.     my ($x,$y,$len,$max,$label,$value)=@$self;
  842.     pv::set_cur_pos($x,$y); pv::bgcolor(6); pv::fgcolor(0);
  843.     &pv::pvprint($label." "); pv::bgcolor(4); pv::fgcolor(15); &pv::pvprint(" ");
  844.     &pv::pvprint(substr($value,$start,$len)); 
  845.     &pv::pvprint("." x ($len - length(substr($value,$start,$len)))); 
  846.     &pv::pvprint (" ");
  847.     pv::bgcolor (6);
  848. }
  849.  
  850. sub display {
  851.     my $self=shift;
  852.     $self->place;
  853.     &pv::refresh();
  854. }
  855.  
  856. sub refresh {
  857.     my $self = shift;
  858.     my $start = shift;
  859.     my $i=shift;
  860.     my ($x,$y,$len,$oldstart,$label,$value)=@$self;
  861.     if ($oldstart == $start) {
  862.         pv::set_cur_pos($x+length($label)+2+$i-$start,$y); 
  863.         pv::bgcolor(4); pv::fgcolor(15);
  864.     &pv::pvprint(substr($value,$i,$len-($i-$start))); 
  865.     &pv::pvprint("." x ($len-($i-$start)-length(substr($value,$i,$len)))); 
  866.         pv::bgcolor (6);
  867.     }
  868.     else {
  869.     $$self[3]=$start;
  870.     pv::set_cur_pos($x+length($label)+2,$y); 
  871.         pv::bgcolor(4); pv::fgcolor(15);
  872.     &pv::pvprint(substr($value,$start,$len)); 
  873.     &pv::pvprint("." x ($len - length(substr($value,$start,$len)))); 
  874.         pv::bgcolor (6);
  875.     }
  876.     &pv::refresh();
  877. }
  878.  
  879. sub activate {            # Makes entryfield active
  880.     my $self = shift;
  881.     my $OVSTRK_MODE=0;
  882.     my ($x,$y,$len,$max,$label)=@$self;
  883.     my $i=0;
  884.     $x += length($label)+2;
  885.     my $start=0; my $savestart=0;
  886.     my $jump=(($len % 2) ? ($len+1)/2 : $len/2);
  887.     $self->refresh($start,$i);
  888.     pv::set_cur_pos($x,$y);
  889.     &pv::refresh_cursor();
  890.     while (@key = pv::getkey()) {
  891.  
  892.     if ($key[1]==7) {    # UpArrow
  893.         $self->refresh(0,0);
  894.         return 1;
  895.     }
  896.     elsif ($key[1]==8) {    # DnArrow
  897.         $self->refresh(0,0);
  898.         return 2;
  899.     }
  900.     elsif ($key[1]==18) {    # Help
  901.         $self->refresh(0,0);
  902.         return 5;
  903.     }
  904.     elsif ($key[1]==19) {    # Menu
  905.         $self->refresh(0,0);
  906.         return 6;
  907.     }
  908.  
  909.     ($key[1]) || do {    # Control-char
  910.         (($key[0] eq "") || ($key[0] eq "")) && do {
  911.         if ($i) {
  912.             $i--;
  913.             substr ($$self[5],$i,1) = "";
  914.             ($i<$start) && ($start -= $jump);
  915.             ($start <0) && ($start = 0);
  916.             $self->refresh($start,$i);
  917.               pv::set_cur_pos($x+$i-$start,$y);
  918.             &pv::refresh_cursor();
  919.         }
  920.         }
  921.     };
  922.     ($key[1]==200) && do {
  923.         if ($key[0] =~ /[\n\r\t\f]/) {
  924.         ($key[0] eq "\t") && do {
  925.             $self->refresh(0,0);
  926.             return 7;
  927.         };
  928.         (($key[0] eq "\n") || ($key[0] eq "\r")) && do {
  929.             $self->refresh(0,0);
  930.             return 8;
  931.         };
  932.         ($key[0] eq "\f") && do {
  933.  
  934.         };
  935.         }
  936.         else {
  937.         substr ($$self[5],$i,$OVSTRK_MODE) = $key[0];
  938.         ($i-$start >= $len) && ($start += $jump);
  939.         $self->refresh($start,$i);
  940.         $i++;
  941.             pv::set_cur_pos($x+$i-$start,$y); 
  942.         &pv::refresh_cursor();
  943.         }
  944.     };
  945.     ($key[1]==1) && do {    # Home
  946.         ($start) && ($self->refresh(0,0));
  947.         $i=0; $start=0;
  948.         pv::set_cur_pos($x,$y);
  949.         &pv::refresh_cursor();
  950.     };
  951.     ($key[1]==2) && do {    # Insert
  952.         $OVSTRK_MODE = ($OVSTRK_MODE ? 0 : 1);
  953.     };
  954.     ($key[1]==3) && do {    # Del
  955.         if ($i < length($$self[5])) {
  956.         substr ($$self[5],$i,1) = "";
  957.         $self->refresh($start,$i);
  958.                 pv::set_cur_pos($x+$i-$start,$y); 
  959.         &pv::refresh_cursor();
  960.         }
  961.     };
  962.     ($key[1]==4) && do {    # End
  963.         $i=length($$self[5]); 
  964.         $savestart=$start;
  965.         ($start+$len <= length($$self[5])) && 
  966.          (($start=$i-$len+1) < 0) && ($start = 0);
  967.         ($savestart != $start) && ($self->refresh($start,$i));
  968.         pv::set_cur_pos($x+$i-$start,$y); 
  969.         &pv::refresh_cursor();
  970.     };
  971.     ($key[1]==9) && do {    # RightArrow
  972.         if ($i < length($$self[5])) {
  973.         $i++;
  974.         $savestart=$start;
  975.         ($i-$start >= $len) && ($start += $jump);
  976.         ($savestart != $start) && ($self->refresh($start,$i));
  977.             pv::set_cur_pos($x+$i-$start,$y);
  978.         &pv::refresh_cursor();
  979.         }
  980.     };
  981.     ($key[1]==10) && do {    # LeftArrow
  982.         if ($i) {
  983.         $i--;
  984.         $savestart=$start;
  985.         ($i<$start) && ($start -= $jump);
  986.         ($start <0) && ($start = 0);
  987.         ($savestart != $start) && ($self->refresh($start,$i));
  988.             pv::set_cur_pos($x+$i-$start,$y); 
  989.         &pv::refresh_cursor();
  990.         }
  991.     };
  992.     }
  993. }
  994.  
  995. sub stat {
  996.     my $self = shift;
  997.     return $$self[5];
  998. }
  999.  
  1000. package PV_Password;
  1001.  
  1002. @ISA = (PV_Entryfield);
  1003.  
  1004. sub new {            # Creates your basic hidden text entry field
  1005.     my $type = shift;        # new PV_Entryfield(x,y,len,max,label,value);
  1006.     my @params = @_;
  1007.     my $self = \@params;
  1008.     bless $self;
  1009. }
  1010.  
  1011. sub place {
  1012.     my $self = shift;
  1013.     my $start = shift;
  1014.     my ($x,$y,$len,$max,$label,$value)=@$self;
  1015.     pv::set_cur_pos($x,$y); pv::bgcolor(6); pv::fgcolor(0);
  1016.     &pv::pvprint($label." "); pv::bgcolor(4); pv::fgcolor(15); &pv::pvprint(" ");
  1017.     &pv::pvprint("*" x (length(substr($value,$start,$len)))); 
  1018.     &pv::pvprint("." x ($len - length(substr($value,$start,$len)))); 
  1019.     &pv::pvprint (" ");
  1020.     pv::bgcolor (6);
  1021. }
  1022.  
  1023. sub display {
  1024.     my $self=shift;
  1025.     $self->place;
  1026.     &pv::refresh();
  1027. }
  1028.  
  1029. sub refresh {
  1030.     my $self = shift;
  1031.     my $start = shift;
  1032.     my $i=shift;
  1033.     my ($x,$y,$len,$oldstart,$label,$value)=@$self;
  1034.     if ($oldstart == $start) {
  1035.         pv::set_cur_pos($x+length($label)+2+$i-$start,$y); 
  1036.         pv::bgcolor(4); pv::fgcolor(15);
  1037.     &pv::pvprint("*" x (length (substr($value,$i,$len-($i-$start))))); 
  1038.     &pv::pvprint("." x ($len-($i-$start)-length(substr($value,$i,$len)))); 
  1039.         pv::bgcolor (6);
  1040.     }
  1041.     else {
  1042.     $$self[3]=$start;
  1043.     pv::set_cur_pos($x+length($label)+2,$y); 
  1044.         pv::bgcolor(4); pv::fgcolor(15);
  1045.     &pv::pvprint("*" x (length(substr($value,$start,$len)))); 
  1046.     &pv::pvprint("." x ($len - length(substr($value,$start,$len)))); 
  1047.         pv::bgcolor (6);
  1048.     }
  1049.     &pv::refresh();
  1050. }
  1051.  
  1052. package PV_Combobox;
  1053.  
  1054. sub new {            # A basic combo-box
  1055. }
  1056.  
  1057. package PV_Viewbox;        
  1058.  
  1059. sub new {            # A readonly text viewer
  1060.     my $type=shift;        # PV_Viewbox (x1,y1,x2,y2,text,top);
  1061.     my @params=(@_,[],[]);
  1062.     my $self=\@params;
  1063.     $$self[4]=~s/[\r\0]//g;    # Strip nulls & DOShit.
  1064.     $$self[4]=~s/\t/        /g;    # TABs = 8 spaces.
  1065.     $$self[4].="\n";
  1066.     my $text = $$self[4];
  1067.     $text=~s/\n/\n\t/g;
  1068.     @{$$self[6]}=split("\t",$text);
  1069.     @{$$self[7]}=();
  1070.     bless $self;
  1071. }
  1072.  
  1073. sub place {
  1074.     my $self=shift;
  1075.     my ($x1,$y1,$x2,$y2,$text,$start)=@$self;
  1076.     my $lines=$y2-$y1-2;
  1077.     my $i=0;
  1078.     $y1++;
  1079.     pv::box(@$self[0..3],0,6);
  1080.     $self->refresh(1);
  1081. }
  1082.  
  1083. sub display {
  1084.     my $self=shift;
  1085.     $self->place;
  1086.     &pv::refresh();
  1087. }
  1088.  
  1089. sub refresh {
  1090.     my $self=shift;
  1091.     my $display=shift;
  1092.     ($$self[5]>($#{$$self[6]}-$$self[3]+$$self[1]+2)) && 
  1093.     ($$self[5]=$#{$$self[6]}-$$self[3]+$$self[1]+2);
  1094.     ($$self[5]<0) && ($$self[5]=0);
  1095.     my ($x1,$y1,$x2,$y2,$text,$start)=@$self;
  1096.     my $lines=$y2-$y1-2;
  1097.     my $l;
  1098.     my $i=0;
  1099.     $y1++; my $len=0;
  1100.     pv::bgcolor(6); pv::fgcolor(0);
  1101.     foreach (@{$$self[6]}[$start..$start+$lines]) {
  1102.     unless ($$self[7][$i] eq $_) {
  1103.         pv::set_cur_pos($x1+2,$y1+$i);
  1104.           $l=$_;
  1105.         $len=length ($$self[7][$i]);
  1106.         $$self[7][$i] = $l;
  1107.         chop ($l);
  1108.         (length($l) > $x2-$x1-3) && ($l=substr($l,0,$x2-$x1-3));
  1109.         &pv::pvprint($l); 
  1110.           if (length($l) < $x2-$x1-3) {
  1111.         &pv::pvprint (" " x ($x2-$x1-3 - length ($l)));
  1112.         }
  1113.     }
  1114.     $i++;
  1115.     }
  1116.     $self->statusbar;
  1117.     ($display) || (&pv::refresh());
  1118. }
  1119.  
  1120. sub statusbar {
  1121. }
  1122.  
  1123. sub activate {            # Makes viewer active
  1124.     my $self = shift;
  1125.     my ($x1,$y1,$x2,$y2,$text,$start)=@$self;
  1126.     $self->refresh;
  1127.     while (@key = pv::getkey()) {
  1128.  
  1129.     if ($key[1]==18) {    # Help
  1130.         $self->refresh;
  1131.         return 5;
  1132.     }
  1133.     elsif ($key[1]==19) {    # Menu
  1134.         $self->refresh;
  1135.         return 6;
  1136.     }
  1137.     ($key[1]==200) && do {
  1138.         if ($key[0] =~ /[\r\t\f]/) {
  1139.         ($key[0] eq "\t") && do {
  1140.             $self->refresh;
  1141.             return 7;
  1142.         };
  1143.         }
  1144.     };
  1145.  
  1146.     ($key[1]==1) && do {    # Home
  1147.         $$self[5]=0;
  1148.         $self->refresh;
  1149.     };
  1150.     ($key[1]==4) && do {    # End
  1151.         $$self[5]=$#{$$self[6]}-$y2+$y1+2;
  1152.         $self->refresh;
  1153.     };
  1154.     ($key[1]==5) && do {    # PgUp
  1155.         $$self[5]-=$y2-$y1-2;
  1156.         $self->refresh;
  1157.     };
  1158.     ($key[1]==6) && do {    # PgDown
  1159.         $$self[5]+=$y2-$y1-2;
  1160.         $self->refresh;
  1161.     };
  1162.     ($key[1]==7) && do {    # UpArrow
  1163.         $$self[5]--;
  1164.         $self->refresh;
  1165.     };
  1166.     ($key[1]==8) && do {    # DownArrow
  1167.         $$self[5]++;
  1168.         $self->refresh;
  1169.     };
  1170.     }
  1171. }
  1172.  
  1173. package PV_Editbox;
  1174.  
  1175. sub new {            # More or less a complete editor
  1176.     my $type=shift;        # PV_Editbox (x1,y1,x2,y2,m,text,index,top);
  1177.     my @params=(@_,[],[],0);
  1178.     my $self=\@params;
  1179.     $$self[5]=~s/[\r\0]//g;    # Strip nulls & DOShit.
  1180.     $$self[5]=~s/\t/        /g;    # TABs = 8 spaces.
  1181.     $$self[5].="\n";
  1182.     bless $self;
  1183.     $self->justify(1);
  1184.     return $self;
  1185. }
  1186.  
  1187. sub place {
  1188.     my $self=shift;
  1189.     my ($x1,$y1,$x2,$y2,$margin,$text,$index,$start)=@$self;
  1190.     my $lines=$y2-$y1-2;
  1191.     my $i=0;
  1192.     $y1++;
  1193.     pv::box(@$self[0..3],0,6);
  1194.     $self->refresh(1);
  1195. }
  1196.  
  1197. sub display {
  1198.     my $self=shift;
  1199.     $self->place;
  1200.     &pv::refresh();
  1201. }
  1202.  
  1203. sub statusbar {
  1204. }
  1205.  
  1206. sub refresh {
  1207.     my $self=shift;
  1208.     my $display=shift;
  1209.     my ($x1,$y1,$x2,$y2,$margin,$text,$index,$start)=@$self;
  1210.     my @visible=@{$$self[9]};
  1211.     my $lines=$y2-$y1-2;
  1212.     my $i=0; my $l;
  1213.     $y1++;
  1214.     pv::bgcolor(6); pv::fgcolor(0);
  1215.     foreach (@{$$self[8]}[$start..$start+$lines]) {
  1216.     unless ($visible[$i] eq $_) {
  1217.         $$self[9][$i] = $_;
  1218.         pv::set_cur_pos($x1+2,$y1+$i);
  1219.          $l=$_;
  1220.         chop ($l);
  1221.         &pv::pvprint($l); &pv::pvprint (" " x (length ($visible[$i]) - length ($l)));
  1222.     }
  1223.     $i++;
  1224.     }
  1225.     $self->statusbar;
  1226.     ($display) || (&pv::refresh());
  1227. }
  1228.  
  1229. sub process_key {
  1230. }
  1231.  
  1232. sub justify {
  1233.     my $self=shift;
  1234.     my $mode=shift;
  1235.     my ($x1,$y1,$x2,$y2,$margin,$text,$index)=@$self;
  1236.     my ($i,$j)=(0,0); my $line; my @text; my $ta; my $tb;
  1237.     my @textqq;
  1238.     substr ($text,$index,0)="\0";
  1239.     $text=~s/ *\n/\n/g;
  1240.     if ($mode) {
  1241.     $ta="";
  1242.     $tb="";
  1243.     }
  1244.     else {
  1245.     $mode=length($text);
  1246.     ($ta,$tb)=split("\0",$text);
  1247.     $ta=$ta."\0";$tb="\0".$tb;
  1248.     $ta=~s/(.*)\n\s.*/$1/s; ($ta=~/\0/) && ($ta="");
  1249.     $tb=~s/.*?\n\s//s; ($tb=~/\0/) && ($tb="");
  1250.     $text=substr($text,length($ta),$mode-(length($ta)+length($tb)));
  1251.     $mode=0;
  1252.     }
  1253.     $text=~s/\n/\n\t/g;
  1254.     my @text=split("\t",$text);
  1255.     my $j=0;
  1256.     for ($i=0; $j<=$#text; $i++) {
  1257.     if (($text[$j] eq "\n") || ($text[$j] eq "\0\n")) {
  1258.         $textqq[$i]=$text[$j];
  1259.     }
  1260.     else {
  1261.         if (length($text[$j]) > $margin) {
  1262.         $line=$text[$j];
  1263.         $text[$j]=substr($text[$j],0,$margin);
  1264.         $text[$j]=~s/^(.*\s+)\S*$/$1/;
  1265.         $line=substr($line,length($text[$j])); 
  1266.         $line=~s/^\s*//;
  1267.         $text[$j]=~s/\s*$/\n/;
  1268.         if (($j==$#text) && ($line)) {
  1269.             $text[$j+1]=$line;
  1270.             @textqq[$i]=$text[$j];
  1271.         }
  1272.         elsif (($line) && 
  1273.                ($text[$j+1]=~/^[\s\0]/)) {
  1274.             $textqq[$i]=$text[$j];
  1275.             $text[$j]=$line; $j--;
  1276.         }
  1277.         else {
  1278.             $line=~s/\n$//;
  1279.             $line=~s/(\S)$/$1 /;
  1280.             $textqq[$i]=$text[$j];
  1281.             $text[$j+1]=$line.$text[$j+1];
  1282.         }
  1283.         }
  1284.         elsif ((!$mode) && 
  1285.            ($j < $#text) &&  
  1286.            (length($text[$j])+
  1287.             length ((split(" ",$text[$j+1]))[0]) < $margin) && 
  1288.            ($text[$j+1] =~ /^[^\s\0]/)) { 
  1289.  
  1290.         chop ($text[$j]);
  1291.         ($text[$j]=~/\s$/) || ($text[$j].=" ");
  1292.         $text[$j].=$text[$j+1];
  1293.         $textqq[$i]=$text[$j];
  1294.         $text[$j+1]=$text[$j];
  1295.         $i--;
  1296.         }
  1297.         else {
  1298.         $textqq[$i]=$text[$j];
  1299.         }
  1300.     }
  1301.     $j++;
  1302.     }
  1303.     $text=join("",@textqq);
  1304.     $text=$ta.$text.$tb;
  1305.     $index=length((split("\0",$text))[0]);
  1306.     substr($text,$index,1)="";
  1307.     $$self[6]=$index;
  1308.     $$self[5]=$text;
  1309.     $text =~ s/\n/\n\t/g;
  1310.     @{$$self[8]}=split("\t",$text);
  1311. }
  1312.  
  1313. sub cursor {
  1314.     my $self=shift;
  1315.     my ($x1,$y1,$x2,$y2,$margin,$text,$index,$start)=@$self;
  1316.     my $textthis=substr($text,0,$index+1);
  1317.     my $col=0;
  1318.     my $line=($textthis =~ tr/\n//);
  1319.     if ($textthis=~/\n$/) {
  1320.     ($line) && ($line--);
  1321.     $col++;
  1322.     }
  1323.     my $len=(length($$self[8][$line])-1);
  1324.     $col+=(length((split("\n",$textthis))[$line]));
  1325.     if ($line<$start) {
  1326.     $start=$line;
  1327.     }
  1328.     elsif ($line>=$start+$y2-$y1-1) {
  1329.     (($start=$line-$y2+$y1+2) <0) && ($start=0);
  1330.     }
  1331.     ($$self[7]!=$start) && do {
  1332.     $$self[7]=$start;
  1333.     $self->refresh;
  1334.     };
  1335.     pv::set_cur_pos($col+$x1+1,$y1+$line-$start+1);
  1336.     return ($col,$line,$len);
  1337. }
  1338.  
  1339. sub linemove {
  1340.     my $self=shift;
  1341.     my $dir=shift;
  1342.     my $count=shift;
  1343.     my ($col, $line, $len) = $self->cursor;
  1344.     if ($dir) {
  1345.     ($line+$count >$#{$$self[8]}) && ($count = $#{$$self[8]} - $line);
  1346.     if ($count) {
  1347.         $$self[6]+=($len-$col+1);
  1348.         (length ($$self[8][$line+$count]) < $col) && 
  1349.         ($col=length ($$self[8][$line+$count]));
  1350.         $$self[6]+=$col;
  1351.         $count--;
  1352.         while ($count) {
  1353.         $$self[6]+=length($$self[8][$count+$line]);
  1354.         $count--;
  1355.         }
  1356.     }
  1357.     }
  1358.     elsif ($line) {
  1359.     ($line - $count <0) && ($count = $line);
  1360.     $$self[6]-=($col+length($$self[8][$line-$count]));
  1361.     (length ($$self[8][$line-$count]) < $col) && 
  1362.         ($col=length ($$self[8][$line-$count]));
  1363.     $$self[6]+=$col;
  1364.     $count--;
  1365.     while ($count) {
  1366.         $$self[6]-=length($$self[8][$line-$count]);
  1367.         $count--;
  1368.     }
  1369.     }
  1370. }
  1371.  
  1372. sub e_bkspc {
  1373.     my $self = shift;
  1374.     my ($col, $line, $len) = $self->cursor;
  1375.     if ($$self[6]) {
  1376.     $$self[6]--;
  1377.     if (substr ($$self[5],$$self[6],1) eq "\n") {
  1378.         substr ($$self[5],$$self[6],1) = "";
  1379.         $self->justify;
  1380.     }
  1381.     else {
  1382.         substr ($$self[5],$$self[6],1) = "";
  1383.         substr ($$self[8][$line],$col-2,1) = "";
  1384.     }
  1385.     $self->refresh;
  1386.     }
  1387. }
  1388.  
  1389. sub e_del {
  1390.     my $self=shift;
  1391.     my ($col, $line, $len) = $self->cursor;
  1392.     unless ($$self[6]==length($$self[5])-1) {
  1393.     if (substr ($$self[5],$$self[6],1) eq "\n") {
  1394.         substr ($$self[5],$$self[6],1) = "";
  1395.         $self->justify;
  1396.     }
  1397.     else {
  1398.         substr ($$self[5],$$self[6],1) = "";
  1399.         substr ($$self[8][$line],$col-1,1) = "";
  1400.     }
  1401.     $self->refresh;
  1402.     }
  1403. }
  1404.  
  1405. sub e_ins {
  1406.     my $self = shift;
  1407.     my $keystroke = shift;
  1408.     my ($col, $line, $len) = $self->cursor;
  1409.     if (substr ($$self[5],$$self[6],1) eq "\n") {
  1410.     substr ($$self[5],$$self[6],0) = $keystroke;
  1411.     substr($$self[8][$line],$col-1,0)=$keystroke;
  1412.     }
  1413.     else {
  1414.     substr ($$self[5],$$self[6],$$self[10]) = $keystroke;
  1415.     substr($$self[8][$line],$col-1,$$self[10])=$keystroke;
  1416.     }
  1417.     $$self[6]++;
  1418.     if ((length($$self[8][$line]) >= $$self[4]) || 
  1419.     ($keystroke eq "\n")) {
  1420.     $self->justify;
  1421.     }
  1422.     $self->refresh;
  1423. }
  1424.  
  1425. sub stat {
  1426.     my $self=shift;
  1427.     return $$self[5];
  1428. }
  1429.  
  1430. sub activate {            # Makes editbox active
  1431.     my $self = shift;
  1432.     my ($y1,$y2,$margin)=($$self[1],$$self[3],$$self[4]);
  1433.     my $exitcode;
  1434.     $self->refresh;
  1435.     my ($col, $line, $len) = $self->cursor;
  1436.     &pv::refresh_cursor();
  1437.     while (@key = pv::getkey()) {
  1438.  
  1439.     if ($key[1]==18) {    # Help
  1440.         $self->refresh;
  1441.         return 5;
  1442.     }
  1443.     elsif ($key[1]==19) {    # Menu
  1444.         $self->refresh;
  1445.         return 6;
  1446.     }
  1447.     else {            # Process key hook for subclasses
  1448.         @exitcode = ($self->process_key (@key));
  1449.         if ($exitcode[0] == 1) {
  1450.         $self->refresh;
  1451.         return 8;
  1452.         }
  1453.         elsif ($exitcode[0] == 2) {
  1454.         }
  1455.         else {        # Now defaults for the editbox.
  1456.         if ($exitcode[0] == 3) {
  1457.             @key = @exitcode[1..2];
  1458.         }
  1459.  
  1460.         ((!$key[1]) && (($key[0] eq "") || ($key[0] eq ""))) && ($self->e_bkspc());
  1461.         (($key[1]==200) && ($key[0] eq "\t")) && do {$self->refresh; return 7;};
  1462.         (($key[1]==200) && ($key[0] =~ /\r\f/)) && do {pv::redraw(); last;};
  1463.         ($key[1]==200) && ($self->e_ins($key[0]));
  1464.         (($key[1]==2) || ($key[1]==21)) && ($$self[10] = ($$self[10] ? 0 : 1)); 
  1465.         (($key[1]==3) || (($key[0] eq "") && (!$key[1]))) && ($self->e_del());
  1466.         
  1467.         (($key[1]==1) || (($key[0] eq "") && (!$key[1]))) && do {    # Home
  1468.             $$self[6]-=(($self->cursor)[0]-1);
  1469.         };
  1470.         (($key[1]==4) || (($key[0] eq "") && (!$key[1]))) && do {    # End
  1471.             $$self[6]+=(($self->cursor)[2] - (($self->cursor)[0]-1));
  1472.         };
  1473.         (($key[1]==5) || ($key[1]==15)) && do {    # PgUp
  1474.             $self->linemove(0,$y2-$y1-2);
  1475.         };
  1476.         (($key[1]==6) || (($key[0] eq "") && (!$key[1]))) && do {    # PgDown
  1477.             $self->linemove(1,$y2-$y1-2);
  1478.         };
  1479.         (($key[1]==7) || (($key[0] eq "") && (!$key[1]))) && do {    # UpArrow
  1480.             $self->linemove(0,1);
  1481.         };
  1482.         (($key[1]==8) || (($key[0] eq "") && (!$key[1]))) && do {    # DownArrow
  1483.             $self->linemove(1,1);
  1484.         };
  1485.         (($key[1]==9) || (($key[0] eq "") && (!$key[1]))) && do {    # RightArrow
  1486.             unless ($$self[6]==length($$self[5])-1) {
  1487.             $$self[6]++;
  1488.             }
  1489.         };
  1490.         (($key[1]==10) || (($key[0] eq "") && (!$key[1]))) && do {    # LeftArrow
  1491.             if ($$self[6]) {
  1492.             $$self[6]--;
  1493.             }
  1494.         };
  1495.         $self->cursor;
  1496.         $self->statusbar;
  1497.         ($col, $line, $len) = $self->cursor;
  1498.         &pv::refresh_cursor();
  1499.         }
  1500.     }
  1501.     }
  1502. }
  1503.  
  1504. package PV_Dialog;
  1505.  
  1506. sub new {            # The dialog box object
  1507.     my $type=shift;        # PV_Dialog ("Label",x1,y1,x2,y2,style,color,
  1508.     my @params=(0,@_);        #            Control1,1,2,3,4,5,6,7,8,
  1509.     my $self=\@params;        #            Control2,1,2,3,4,5,6,7,8,...)
  1510.     bless $self;      
  1511. }
  1512.  
  1513. sub display {
  1514.     my $self=shift;
  1515.     $$self[0]=&pv::pv_tellregion($$self[2],$$self[3],$$self[4]+1,$$self[5]);
  1516.     &pv::box(@$self[2..7]);
  1517.     my $i=8;
  1518.     while ($i+7 < $#$self) {
  1519.     ($$self[$i])->place;
  1520.     $i+=9;
  1521.     }
  1522.     &pv::refresh;
  1523. }
  1524.  
  1525. sub activate {
  1526.     my $self=shift;
  1527.     $self->display;
  1528.     my $i=1; my @last=();
  1529.     while ($i) {
  1530.     @last=($i,($$self[8+(($i-1)*9)]->activate));
  1531.     $i=$$self[8+(($i-1)*9)+$last[1]];
  1532.     }
  1533.     $self->hide;
  1534.     &pv::refresh();
  1535.     return (@last);
  1536. }
  1537.  
  1538. sub hide {
  1539.     my $self=shift;
  1540.     ($$self[0]) && (&pv::pv_putregion($$self[2],$$self[3],$$self[4]+1,$$self[5],$$self[0]));
  1541.     $$self[0]=0;
  1542. }
  1543.  
  1544. package PVD;            # Two commonly needed dialog box types
  1545.  
  1546. sub message {
  1547.     my ($message,$width,$depth)=@_;
  1548.     ($width<11) && ($width=11);
  1549.     $depth+=4;
  1550.     my $x1=int ((80-$width)/2);
  1551.     my $y1=4 + int ((19-$depth)/2);
  1552.     my $x2=$x1+$width;
  1553.     my $y2=$y1+$depth;
  1554.     my $static=new PV_Static($message,$x1+2,$y1+1,$x2,$y2-4);
  1555.     my $ok = new PV_Cutebutton(" OK ",$x1+int($width/2)-3,$y2-2);
  1556.     my $dialog = new PV_Dialog ("",$x1,$y1,$x2,$y2,1,6,
  1557.                 $ok,1,1,1,1,1,1,1,0,
  1558.                 $static,0,0,0,0,0,0,0,0);
  1559.     $dialog->activate;
  1560. }
  1561.  
  1562. sub yesno {
  1563.     my ($message,$width,$depth)=@_;
  1564.     my @message=split("\n",$message);
  1565.     ($width<21) && ($width=21);
  1566.     $depth+=4;
  1567.     my $x1=int ((80-$width)/2);
  1568.     my $y1=4 + int ((19-$depth)/2);
  1569.     my $x2=$x1+$width;
  1570.     my $y2=$y1+$depth;
  1571.     my $static=new PV_Static($message,$x1+2,$y1+1,$x2,$y2-4);
  1572.     my $yes = new PV_Cutebutton (" YES ",$x1+int($width/2)-9,$y2-2);
  1573.     my $no = new PV_Cutebutton (" NO ",$x1+int($width/2)+2,$y2-2);
  1574.     my $dialog = new PV_Dialog ("",$x1,$y1,$x2,$y2,1,6,
  1575.                 $yes,1,1,2,1,1,1,2,0,
  1576.                 $no,2,3,2,1,2,2,1,0,
  1577.                 $static,0,0,0,0,0,0,0,0);
  1578.     my $stat=($dialog->activate)[0];
  1579.     ($stat==2) && ($stat=0);
  1580.     return $stat;
  1581. }
  1582.  
  1583. "PerlVision. (C) Ashish Gulhati, 1995";
  1584.